fix(proxy): report eligible pool usage exhaustion as 429 - #1541
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d73fd3869d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
acbf7a4 to
9eb44ab
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
cd1f47a to
97194be
Compare
The takeover of #1247 hardens selection_failure_response: instead of a private duplicate of the account-cap code set, local capacity codes are resolved via app.core.resilience.overload.LOCAL_OVERLOAD_CODES. This keeps every local overload code (including codes added later, such as the congestion fair-share code from #1536) on the stable 429 rate_limit_error contract, and guarantees the new usage_limit_reached 429 mapping is applied strictly to upstream usage/quota exhaustion of the whole eligible pool. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds externally-routed regressions for the takeover of #1247: - /v1/responses and /backend-api/codex/responses return HTTP 429 with error.type = error.code = usage_limit_reached (and authoritative error.resets_at) when every eligible account is usage-exhausted - resets_at is omitted when selection has no authoritative reset - paused/deactivated/reauth-only pools keep the pre-existing no_accounts semantics, and the synthetic SSE failure keeps the #1479 sequenced response.created/response.failed SDK stream contract - one usable account still fails over with no error Also tightens the OpenSpec delta: authoritative-reset-only resets_at, terminal (non-waitable) usage-limit failures, local capacity codes keep their rate_limit_error contract, owner-scoped exhaustion keeps continuity semantics. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
97194be to
cdf2a27
Compare
When every account eligible for a Responses request is exhausted by an upstream usage/quota window, codex-lb previously collapsed the failure into a generic
502/503no_accounts, which makes Codex mark persisted Goalsblockedinstead ofusageLimited. This change classifies pool-wide exhaustion structurally (no retry-text parsing) and returns the Codex-compatible contract:{"error": {"message": "…", "type": "usage_limit_reached", "code": "usage_limit_reached"}}with HTTP
429, pluserror.resets_atonly when account selection holds an authoritative upstream reset for an actually exhausted window (never the capped human retry hint or a synthesized fallback).Closes #1246.
Supersedes #1247 — original implementation by @glopyglerky, taken over per the 07-27 maintainer notice. The author's 10 commits are preserved with original authorship; takeover commits sit on top.
Behavior matrix (#1246)
429 usage_limit_reached(+ authoritativeresets_at)no_accountssemanticsLOCAL_OVERLOAD_CODESmember, including codes added later such asapi_key_stream_fair_sharefrom feat(proxy): congestion-aware per-API-key fair-share stream admission #1536) → existing429 rate_limit_error502429 usage_limit_reachedRebase notes
mainacross the_load_balancer/package extraction, fix(proxy): spill unanchored forks on account caps #1499 (unanchored-fork spillover) and fix(proxy): release idle bridge sessions' account stream leases #1476 (idle bridge lease release); the author's balancer-loop changes were ported intounbound_selection.py/sticky_selection.py.429exits as an HTTP response before_normalize_public_responses_stream; streamed selection failures keep the sequenced syntheticresponse.created→response.failedcontract (pinned by integration test).selection_failure_responseresolves local capacity codes against the canonicalLOCAL_OVERLOAD_CODESregistry so the new 429 mapping is strictly for upstream usage exhaustion.OpenSpec
openspec/changes/report-pool-usage-exhaustion/(delta onresponses-api-compat), extended for authoritative-reset-onlyresets_at, terminal usage-limit failures, local-capacity contract preservation, and owner-scope continuity.openspec validate report-pool-usage-exhaustion --strictpasses.Testing
ruff check+ruff format --check+scripts/check_proxy_architecture.py+uv run ty check: passtests/unit/test_load_balancer*.py,test_selection_errors.py,test_openai_errors.py,test_proxy_http_bridge.py,test_proxy_utils.py,tests/integration/test_proxy_responses.py,test_http_responses_bridge.py,test_proxy_api_extended.py— 1,919 tests passed/v1/responsesand/backend-api/codex/responses,resets_atpresence/omission, and the fix(proxy): sequence synthetic Responses failures #1479 sequenced SSE failure contract.🤖 Generated with Claude Code